package com.cmc6.common.util;

import cn.hutool.core.util.RandomUtil;
import com.cmc6.common.properties.SmsTencentProperties;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import com.tencentcloudapi.sms.v20210111.models.SendStatus;
import lombok.SneakyThrows;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * 腾讯：短信工具类
 */
@Component
public class SmsTencentUtil {

    public static SmsTencentProperties smsTencentProperties;

    @Resource
    private void setSmsTencentProperties(SmsTencentProperties val) {
        SmsTencentUtil.smsTencentProperties = val;
    }

    public static RedisTemplate<String, String> redisTemplate;

    @Resource
    private void setRedisTemplate(RedisTemplate<String, String> val) {
        SmsTencentUtil.redisTemplate = val;
    }

    public static RedissonClient redissonClient;

    @Resource
    private void setRedissonClient(RedissonClient val) {
        SmsTencentUtil.redissonClient = val;
    }

    /**
     * 发送：绑定手机
     */
    public static String sendBind(String phoneNumber) {

        String code = RandomUtil.randomNumbers(6);
        String[] templateParamSet = {code, "10"};
        doSend("1389707", templateParamSet, new String[] {phoneNumber});

        return code;

    }

    /**
     * 发送：修改手机
     */
    public static String sendUpdate(String phoneNumber) {

        String code = RandomUtil.randomNumbers(6);
        String[] templateParamSet = {code, "10"};
        doSend("1389628", templateParamSet, new String[] {phoneNumber});

        return code;

    }

    /**
     * 发送：忘记密码
     */
    public static String sendForgotPassword(String phoneNumber) {

        String code = RandomUtil.randomNumbers(6);
        String[] templateParamSet = {code};
        doSend("1381647", templateParamSet, new String[] {phoneNumber});

        return code;
    }

    /**
     * 发送：登录短信
     */
    public static String sendLogin(String phoneNumber) {

        String code = RandomUtil.randomNumbers(6);
        String[] templateParamSet = {code, "10"};
        doSend("1381644", templateParamSet, new String[] {phoneNumber});

        return code;
    }

    /**
     * 发送：注册短信
     */
    public static String sendReg(String phoneNumber) {

        String code = RandomUtil.randomNumbers(6);
        String[] templateParamSet = {code, "10"};
        doSend("1380202", templateParamSet, new String[] {phoneNumber});

        return code;
    }

    /**
     * 执行：发送短信
     */
    @SneakyThrows
    private static void doSend(String templateId, String[] templateParamSet, String[] phoneNumberSet) {

        /* 必要步骤：
         * 实例化一个认证对象，入参需要传入腾讯云账户密钥对secretId，secretKey。
         * 这里采用的是从环境变量读取的方式，需要在环境变量中先设置这两个值。
         * 你也可以直接在代码中写死密钥对，但是小心不要将代码复制、上传或者分享给他人，
         * 以免泄露密钥对危及你的财产安全。
         * SecretId、SecretKey 查询: https://console.cloud.tencent.com/cam/capi */
        Credential cred = new Credential(smsTencentProperties.getSecretId(), smsTencentProperties.getSecretKey());

        ClientProfile clientProfile = new ClientProfile();

        SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);

        SendSmsRequest req = new SendSmsRequest();

        /* 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId，示例如1400006666 */
        // 应用 ID 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看
        req.setSmsSdkAppId(smsTencentProperties.getSdkAppId());

        /* 短信签名内容: 使用 UTF-8 编码，必须填写已审核通过的签名 */
        // 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-sign) 的签名管理查看
        req.setSignName(smsTencentProperties.getSignName());

        /* 模板 ID: 必须填写已审核通过的模板 ID */
        // 模板 ID 可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-template) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-template) 的正文模板管理查看
        req.setTemplateId(templateId);

        /* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致，若无模板参数，则设置为空 */
        req.setTemplateParamSet(templateParamSet);

        /* 下发手机号码，采用 E.164 标准，+[国家或地区码][手机号]
         * 示例如：+8613711112222， 其中前面有一个+号 ，86为国家码，13711112222为手机号，最多不要超过200个手机号 */
        for (int i = 0; i < phoneNumberSet.length; i++) {
            if (!phoneNumberSet[i].startsWith("+")) {
                // 如果不是加号开头的手机号
                phoneNumberSet[i] = "+86" + phoneNumberSet[i]; // 则增加默认值： +86
            }
        }
        req.setPhoneNumberSet(phoneNumberSet);

        /* 用户的 session 内容（无需要可忽略）: 可以携带用户侧 ID 等上下文信息，server 会原样返回 */
        String sessionContext = "";
        req.setSessionContext(sessionContext);

        /* 短信码号扩展号（无需要可忽略）: 默认未开通，如需开通请联系 [腾讯云短信小助手] */
        String extendCode = "";
        req.setExtendCode(extendCode);

        /* 国际/港澳台短信 SenderId（无需要可忽略）: 国内短信填空，默认未开通，如需开通请联系 [腾讯云短信小助手] */
        String senderid = "";
        req.setSenderId(senderid);

        /* 通过 client 对象调用 SendSms 方法发起请求。注意请求方法名与请求对象是对应的
         * 返回的 res 是一个 SendSmsResponse 类的实例，与请求对象对应 */
        SendSmsResponse res = client.SendSms(req);

        if (res.getSendStatusSet().length == 0) {
            ApiResult.error("短信发送失败，请联系管理员");
        }

        SendStatus sendStatus = res.getSendStatusSet()[0];
        String code = sendStatus.getCode();
        if (!"Ok".equals(code)) {
            throw new RuntimeException("短信发送失败，code：【" + code + "】"); // 这里会触发 错误日志功能
        }

    }

}
